import Page
import allure
import pymongo
from sshtunnel import SSHTunnelForwarder
from Base.base_data import Setting as a


# 生成server, client,给下面的方法使用
def mongodb_client():
    # 打开ssh通道
    server = SSHTunnelForwarder(
        ssh_address_or_host=(a.ssh_host, a.ssh_port),
        ssh_username=a.DB_username,
        ssh_password=a.DB_pwd,
        remote_bind_address=(a.mongodb_host,a.mongodb_port))
    server.start()
    # 建立直连mongodb客户端
    uri = "mongodb://%s:%s@%s:%s" % ("root", "qn7XrrXRDtR6QBv82xqMi", "127.0.0.1", server.local_bind_port)
    client = pymongo.MongoClient(uri)  ## 这里一定要填入ssh映射到本地的端口
    return server, client


# 断言 -->应用名在mongodb中【db删除应用/应用断言使用】True/False
@allure.step(title="断言应用信息在mongodb中")
def if_app_name_in_mongodb(app_name, description):
    try:
        # 创建mongodb连接
        client = mongodb_client()
        # # 选择连接的库
        my_db = client[1]["businessdb"]
        # # 选择连接的表
        my_col = my_db["access"]
        # 查询条件,账号下所有此应用名
        num = 0
        if app_name == 1:
            app_name = "app_auto"
        if len(app_name) > 20:
            app_name = app_name[:20]
        my_query = {"account_id": a.account_id, "app_name": app_name}
        my_doc = my_col.find(my_query, {"_id": 0, "app_name": 1})
        value_all = []
        for x in my_doc:
            value_all.append(x)
        allure.attach("mongodb中应用名", "{}".format(value_all))
        # 断言 -->keyword in expect结果 判断数据库是否存在此应用名
        if db_if_include(app_name, str(value_all)):
            num += 1
        if description == 1:
            description = "description_auto"
        if description == None:
            # 断言 -->actual结果 == expect结果
            return db_if_equal(num, 1)
        if len(description) >20:
            # 断言 -->actual结果 == expect结果
            return db_if_equal(num, 1)
        else:
            my_query = {"account_id":a.account_id, "description": description}
            my_doc = my_col.find(my_query, {"_id": 0, "description": 1})
            value_all = []
            for x in my_doc:
                value_all.append(x)
            allure.attach("mongodb中应用描述", "{}".format(value_all))
            # 断言 -->keyword in expect结果 判断数据库是否存在此应用名
            if db_if_include(description, str(value_all)):
                num += 1
            # 断言 -->actual结果 == expect结果
            return db_if_equal(num, 2)
    except Exception as e:
        allure.attach("失败描述", "断言应用名在DB中失败,原因：{}".format(e))
        assert False
    finally:
        # 关闭mongodb连接
        client[1].close()
        # 关闭ssh通道连接
        client[0].close()


# 断言 -->设备空间在mongodb中【设备空间断言使用】True/False
@allure.step(title="断言设备空间在mongodb中")
def if_space_name_in_mongodb(space_name):
    try:
        # 创建mongodb连接
        client = mongodb_client()
        # # 选择连接的库
        my_db = client[1]["businessdb"]
        # # 选择连接的表
        my_col = my_db["device_space"]
        # 查询条件,账号下所有此应用名
        if len(space_name) > 20:
            space_name = space_name[:20]
        my_query = {"app_id": a.app_id, "name": space_name}
        my_doc = my_col.find(my_query, {"_id": 0, "name": 1})
        value_all = []
        for x in my_doc:
            value_all.append(x)
        allure.attach("db描述", "mongodb中应用名:{}".format(value_all))
        # 断言 -->keyword in expect结果 判断数据库是否存在此应用名
        return db_if_include(space_name, str(value_all))
    except Exception as e:
        allure.attach("失败描述", "断言设备空间在DB中失败,原因：{}".format(e))
        return False
    finally:
        # 关闭mongodb连接
        client[1].close()
        # 关闭ssh通道连接
        client[0].close()


# 断言 -->mongodb中ota_version == 配置version【升级IPC断言使用】True/False
@allure.step(title="断言mongodb中ota_version == 配置version")
def if_mongodb_ota_version_equal(version, device_ip='10.64.31.43'):
    log.info("【断言mongodb中ota_version == 配置version】")
    try:
        # 创建mongodb连接
        client = mongodb_client()
        # 选择连接的库
        my_db = client[1]["iotaccess"]
        # 选择连接的表
        my_col = my_db["mini.inv.devices"]
        # 查询条件,账号下所有此应用名
        my_query = {"attributes.ip.value": device_ip}
        my_doc = my_col.find(my_query, {"_id": 0, "attributes.sys_ver.value": 1})
        value_all = []
        for x in my_doc:
            value_all.append(x)
        allure.attach("mongodb中ota版本", "{}".format(value_all[0]["attributes"]["sys_ver"]["value"]))
        # 断言 -->actual结果 == expect结果 判断mongodb中的版本==version
        return db_if_equal(value_all[0]["attributes"]["sys_ver"]["value"], version)
    except Exception as e:
        allure.attach("失败描述", "断言mongodb中ota_version == 配置version,原因：{}".format(e))
        return False
    finally:
        # 关闭mongodb连接
        client[1].close()
        # 关闭ssh通道连接
        client[0].close()


# 数据清除 -->删除mongodb中app_name 【修改应用使用】
@allure.step(title="数据清除 -->删除mongodb中app_name")
def del_app_name_in_mongodb(app_name, description=None):
    try:
        # 创建mongodb连接
        client = mongodb_client()
        # # 选择连接的库
        my_db = client[1]["businessdb"]
        # # 选择连接的表
        my_col = my_db["access"]
        # 查询条件,账号下所有此应用
        if app_name == 1:
            app_name = "app_auto"
        if len(app_name) > 20:
            app_name = app_name[:20]
        myquery = {"account_id": a.account_id, "app_name": app_name}
        log.info("mongodb查询条件：{}".format(myquery))
        # 调用 断言应用名app_name在mongodb中
        if if_app_name_in_mongodb(app_name, description):
            # 删除应用
            my_col.delete_one(myquery)
            # 断言 -->actual结果 == expect结果
            if db_if_equal(if_app_name_in_mongodb(app_name, description), False):
                allure.attach("正确描述", "mongodb中已删除app_name：{}".format(app_name))
                return True
        else:
            allure.attach("正确描述", "mongodb中不存在该app_name")
            log.info("mongodb中不存在该app_name")
            return True
    except Exception as e:
        allure.attach("错误描述", "mongodb中删除app_name失败,原因:{}".format(e))
        assert False
    finally:
        # 关闭mongodb连接
        client[1].close()
        # 关闭ssh通道连接
        client[0].close()


# mongodb获取 -->返回账号下所有应用名【设备空间搜索框断言使用】list
def get_app_text(return_key, search_text):
    """
    :param return_key: access表中需要返回的字段，输入app_id/app_name
    :param search_text: 搜索的内容
    :return: 账号下所有 app_id/app_name
    """
    try:
        # 创建mongodb连接
        client = mongodb_client()
        # # 选择连接的库、表
        my_db = client[1]["businessdb"]
        my_col = my_db["access"]
        # 获取账号下所有应用名
        my_query = {"account_id": a.account_id}
        my_doc = my_col.find(my_query, {"_id": 0, return_key: 1})
        value_all = []
        for x in my_doc:
            x = x.get(return_key)
            if (search_text in x) or (search_text == x):
                value_all.append(x)
        log.info("账号下所有应用名:{}".format(value_all))
        return value_all
    except Exception as e:
        allure.attach("失败描述", "mongodb取app_text失败,原因：{}".format(e))
        return None
    finally:
        # 关闭mongodb连接
        client[1].close()
        # 关闭ssh通道连接
        client[0].close()


# mongodb获取 -->返回app_id/app_name/space_name数量 【设备空间搜索框断言使用】int
@allure.step(title="mongodb获取 -->返回app_id/app_name/space_name数量")
def get_name_num(return_key, search_text):
    """
    :param return_key: access表中需要返回的字段，输入app_id/app_name
    :param search_text: 搜索的内容
    :return: 账号下所有应用名及设备空间名数量
    """
    try:
        # 创建mongodb连接
        client = mongodb_client()
        # # 选择连接的库、表
        my_db = client[1]["businessdb"]
        # 获取第一个应用下所有设备空间名
        my_col2 = my_db["device_space"]
        my_query = {"app_id": a.app_id}
        my_doc2 = my_col2.find(my_query, {"_id": 0, "name": 1})
        value_all = get_app_text(return_key, search_text)
        for x in my_doc2:
            x = x.get("name")
            if (search_text in x) or (search_text == x):
                value_all.append(x)
        allure.attach("DB符合条件的app_id/app_name/space_name", "{}".format(value_all))
        allure.attach("all_text_num", "{}".format(len(value_all)))
        return len(value_all)
    except Exception as e:
        allure.attach("失败描述", "mongodb取all_text失败,原因：{}".format(e))
        return None
    finally:
        # 关闭mongodb连接
        client[1].close()
        # 关闭ssh通道连接
        client[0].close()


# 断言 -->actual结果 == expect结果 【所有db断言两个值相等使用】
@allure.step("断言actual结果 == expect结果")
def db_if_equal(actual, expect):
    try:
        if actual == expect:
            allure.attach("断言描述", '断言成功：实际结果[{f}]，预期结果[{s}]'.format(f=actual, s=expect))
            return True
        else:
            allure.attach("断言描述", '断言失败：实际结果[{f}]，预期结果[{s}]'.format(f=actual, s=expect))
            return False
    except Exception as e:
        allure.attach("失败描述", '断言两值相等错误，原因：{}'.format(e))
        assert False


# 断言 -->keyword in expect结果 【所有db断言包含使用】
@allure.step("断言keyword in expect结果")
def db_if_include(keyword, expect):
    try:
        if str(keyword) in str(expect):
            allure.attach("断言描述", '断言成功：实际结果[{f}]，预期结果[{s}]'.format(f=keyword, s=expect))
            return True
        else:
            allure.attach("断言描述", '断言失败：实际结果[{f}]，预期结果[{s}]'.format(f=keyword, s=expect))
            return False
    except Exception as e:
        allure.attach("失败描述", '断言keyword in expect结果错误，原因：{}'.format(e))
        assert False


if __name__ == '__main__':
    # 测试
    del_app_name_in_mongodb("213")
